package buco.integrity.communication;

import buco.core.api.*;

import java.util.*;

public class CommunicationIntegrityCheck extends IntegrityCheck {
	
	@Override
	public void checkIntegrity(Bundle bundle, IntegrityReport report) {
		ConnectionsConstraint incoming = bundle.getSemanticConstraint("incomingConnections", 
				ConnectionsConstraint.class);
		
		ConnectionsConstraint outgoing = bundle.getSemanticConstraint("outgoingConnections", 
				ConnectionsConstraint.class);
		
		if(incoming != null) {
			List<BundleWire> wiresIn = composition.getIncomingWires(bundle, true);
			checkInConnections(wiresIn, outgoing, report);
		}
		
		if(outgoing != null) { 
			List<BundleWire> wiresOut = composition.getOutgoingWires(bundle, true);
			checkOutConnections(wiresOut, outgoing, report);
		}
	}
	
	private void checkInConnections(List<BundleWire> wires, ConnectionsConstraint constraint, IntegrityReport report) { 
		if(wires.size() > constraint.numberOfConnections()) { 
			report.warn("Too many incoming connections."); 
		}
		else if(wires.size() < constraint.numberOfConnections()) { 
			report.warn("Insufficient number of incoming connections."); 
		}
		
		for(BundleWire wire : wires) {
			Bundle bundle = wire.getFrom();
			String bundleName = bundle.getBundleSymbolicName(); 
			if(!constraint.isBundleConnected(bundleName)) {
				report.warn(String.format("Missing imcoming connection from bundle %s", bundleName));
			}
		}
	}
	
	private void checkOutConnections(List<BundleWire> wires, ConnectionsConstraint constraint, IntegrityReport report) { 
		if(wires.size() > constraint.numberOfConnections()) { 
			report.warn("Too many outgoing connections."); 
		}
		else if(wires.size() < constraint.numberOfConnections()) { 
			report.warn("Insufficient number of outgoing connections."); 
		}
		
		for(BundleWire wire : wires) {
			Bundle bundle = wire.getTo();
			String bundleName = bundle.getBundleSymbolicName(); 
			if(!constraint.isBundleConnected(bundleName)) {
				report.warn(String.format("Missing outgoing connection to bundle %s", bundleName));
			}
		}
	}
}
